from flask import Response, jsonify, Flask, request, Blueprint,url_for
from configs import *
from modules.Tables import *
from sqlalchemy import func
from Hik_tools.OpenApi_public_Class import *
from sqlalchemy.exc import IntegrityError



# 创建蓝图，对应的register目录（激活操作视图）
hik_security_platform_info_view = Blueprint('hik_security_platform_info_view', __name__)

# 海康安防平台区域数据接入（安防平台）
@hik_security_platform_info_view.route('/hik_security_platform_add', methods=['POST'])
# @jwt_required()
def hik_security_platform_add():
    """
    获取安防平台视频区域信息
    :param hik_host: 主机地址
    :param hik_port: 端口号
    :param hik_appKey: 应用的 AppKey
    :param hik_appSecret: 应用的 AppSecreta
    :param hik_artemis: Artemis路径
    :param hik_methon: 请求方法（如 POST/GET）
    :return: 视频区域列表或错误信息
    """

    # 安防平台接入ip地址
    hik_host = strip_whitespace(request.form.get('hik_host',None))
    # 安防平台接入ip端口
    hik_port = strip_whitespace(request.form.get('hik_port',443))
    # 安防平台接入appKey
    hik_appKey = strip_whitespace(request.form.get('hik_appKey',None))
    # 安防平台接入appSecret
    hik_appSecret = strip_whitespace(request.form.get('hik_appSecret',None))
    # 矿名称id
    Mine_id = strip_whitespace(request.form.get('Mine_id',None))


    # 参数构建判断是否为空
    params = [hik_host, hik_port, hik_appKey, hik_appSecret, Mine_id]

    if not all(params):
        return jsonify({'code': 400, 'msg': '设备数据有未填写项'})

    # 组装https
    hik_host = 'https://{}'.format(hik_host)

    # 配置相关参数
    hik_api = HikVisionAPI(
        host=hik_host,
        port=hik_port,
        app_key=hik_appKey,
        app_secret=hik_appSecret
    )

    try:

        # 获取安防平台主平台名称
        area_records, equipment_records = [], []  # 用于存储区域和设备记录

        # 获取安防平台主平台名称
        area_data = hik_api.get_video_area()

        # 查询安防平台主平台信息
        existing_hik_info = db.session.query(Hik_security_platform_info).filter_by(
            hik_appKey=hik_appKey, hik_appSecret=hik_appSecret
        ).first()

        if not existing_hik_info:
            hik_info_data = Hik_security_platform_info(
                hik_name=area_data[0].get('name'),
                hik_host=hik_host,
                hik_port=hik_port,
                hik_appKey=hik_appKey,
                hik_appSecret=hik_appSecret,
                Mine_id=Mine_id,
            )
            db.session.add(hik_info_data)
            db.session.flush()  # 获取自增ID
            db.session.refresh(hik_info_data)  # 刷新对象，确保ID填充
        else:
            return jsonify({'code':400,'msg':'该安防平台信息已经存在!'})

        for area in area_data:
            # 检查区域是否已存在
            existing_area = db.session.query(Hik_security_platform_up_area).filter_by(
                indexCode=area.get('indexCode'), name=area.get('name')
            ).first()

            if not existing_area:
                # 添加区域记录
                area_record = Hik_security_platform_up_area(
                    indexCode=area.get('indexCode'),
                    name=area.get('name'),
                    hik_info_id=hik_info_data.id,
                    Mine_id=Mine_id,
                    # 其他字段...
                )

                db.session.add(area_record)
                db.session.flush()  # 获取 area_record.id
                db.session.refresh(area_record)  # 刷新对象，确保ID填充

                # 将区域记录添加到批量插入列表
                area_records.append(area_record)

                # 添加设备记录
                eq_record = Equipment(
                    equipment_type='安防平台',
                    manufacturer_type='海康',
                    equipment_name=area.get('name'),
                    Mine_id=Mine_id,
                    Hik_id=area_record.id,  # 使用刚刚 flush 后的 area_record.id
                    Hik_indexCode=area.get('indexCode'),
                )
                db.session.add(eq_record)
                db.session.flush()  # 获取 eq_record.id
                db.session.refresh(eq_record)  # 刷新对象，确保ID填充

                # 将设备记录添加到批量插入列表
                equipment_records.append(eq_record)
                import concurrent.futures

                # 添加子设备记录的函数
                def fetch_rtsp_url_for_child(child_index_code):
                    """ 获取单个子设备的 RTSP URL """
                    return hik_api.get_rtsp_url(child_index_code)

                # 添加子设备记录
                child_data = hik_api.get_video_area_info(area.get('indexCode'))

                # 判断当类型为列表的时候
                if isinstance(child_data, list):
                    print("sub_resources 是列表类型")

                # 判断当类型为 dict 的时候
                elif isinstance(child_data, dict):
                    print("sub_resources 是字典类型")
                    child_data = child_data['data']['list']

                else:
                    print(f"sub_resources 是 {type(child_data).__name__} 类型，暂不处理")
                    child_data = []

                # 并发获取所有子设备的 RTSP URL
                with concurrent.futures.ThreadPoolExecutor() as executor:

                    # 获取所有 child 的 indexCode
                    child_index_codes = [child.get('indexCode') for child in child_data]

                    # 并发请求所有 RTSP URL
                    rtsp_urls = list(executor.map(fetch_rtsp_url_for_child, child_index_codes))

                # 处理每个子设备
                for child, rtsp_url in zip(child_data, rtsp_urls):
                    child_eq_record = Equipment(
                        equipment_type='安防平台',
                        manufacturer_type='海康',
                        equipment_name=child.get('name'),
                        Mine_id=Mine_id,
                        parent_id=eq_record.id,  # 使用刚刚 flush 后的 eq_record.id
                        Hik_id=area_record.id,  # 使用刚刚 flush 后的 area_record.id
                        Hik_indexCode=child.get('indexCode'),
                        Hik_rtsp_url=rtsp_url  # 使用并发获取到的 RTSP URL
                    )
                    db.session.add(child_eq_record)
                    equipment_records.append(child_eq_record)

        # 批量插入区域和设备记录
        try:
            # 尝试插入区域记录
            if area_records:
                db.session.bulk_save_objects(area_records)

            # 尝试插入设备记录
            if equipment_records:
                for eq_record in equipment_records:
                    try:
                        db.session.add(eq_record)  # 单条插入时，处理 IntegrityError
                        db.session.commit()  # 提交单条记录
                    except IntegrityError as e:
                        db.session.rollback()  # 仅回滚当前记录
                        print(f"⚠️ 跳过重复设备记录: {eq_record.Hik_indexCode}, 错误: {e}")
                        continue  # 跳过当前设备，继续插入下一个

            # 提交所有其他区域记录
            db.session.commit()  # 提交数据库事务
        except Exception as e:
            db.session.rollback()  # 发生错误时回滚整个事务
            print(f"批量插入失败: {e}")

        print(f"插入了 {len(area_records)} 个区域记录和 {len(equipment_records)} 个设备记录")

    except Exception as e:
        db.session.rollback()
        print(e)
        return jsonify({'code':400,'msg':'存在无效参数 ,请检查信息！','error':e})
    return jsonify({'code':200,'msg':'安防平台区域信息写入成功'})


# 海康安防平台资源信息联动删除（安防平台）
@hik_security_platform_info_view.route('/hik_security_platform_delete', methods=['POST'])
def hik_security_platform_delete():
    """
    删除安防平台信息及其关联的下级区域和监控点信息。

    参数:
        id (str): 安防平台信息的主键 ID。
    """
    try:
        # 获取并校验参数
        id = strip_whitespace(request.form.get('id', None))
        if not id:
            return jsonify({'code': 400, 'msg': '参数缺失，请提供有效的 ID！'})

        # 开启数据库事务
        with db.session.begin():
            # 查询主区域信息是否存在
            hik_info = db.session.query(Hik_security_platform_info).filter_by(id=id).first()
            if not hik_info:
                return jsonify({'code': 404, 'msg': '未找到对应的安防平台信息！'})

            # 查询并删除下级区域及其关联的监控点
            hik_areas = db.session.query(Hik_security_platform_up_area).filter_by(hik_info_id=hik_info.id).all()
            for area in hik_areas:
                # 删除下级区域的监控点
                db.session.query(Equipment).filter_by(Hik_id=area.id).delete()

            # 删除下级区域
            db.session.query(Hik_security_platform_up_area).filter_by(hik_info_id=hik_info.id).delete()

            # 删除主区域信息
            db.session.delete(hik_info)

        # 提交事务
        db.session.commit()
        return jsonify({'code': 200, 'msg': '删除成功！'})

    except Exception as e:
        db.session.rollback()  # 回滚事务
        return jsonify({'code': 500, 'msg': f'删除失败，错误信息：{str(e)}'})


# 海康安防平台信息展示（安防平台）
@hik_security_platform_info_view.route('/hik_security_platform_data', methods=['GET'])
@jwt_required()
@jwt_required_with_refresh
def hik_security_platform_data():
    """
    海康安防平台信息展示
    """

    # 获取分页参数
    page = request.args.get('page', default=1, type=int)
    per_page = request.args.get('per_page', default=15, type=int)

    # 查询主区域点并进行分页
    pagination = db.session.query(Hik_security_platform_info).paginate(page=page, per_page=per_page, error_out=False)

    # 初始化用于存储结果的数据列表
    data_list = []

    # 遍历分页后的主区域数据
    for main_area in pagination.items:
        # 查询下级区域数据信息
        area_data = convert_folder_to_dict_list(
            db.session.query(Hik_security_platform_up_area).filter(
                Hik_security_platform_up_area.hik_info_id == main_area.id
            ).all(),
            ['id','indexCode', 'name', 'hik_info_id',
             'created_at', 'updated_at']
        )

        # 组装主区域数据并添加下级区域数据
        data_list.append({
            'id':main_area.id,
            'hik_name': main_area.hik_name,
            'hik_host': main_area.hik_host,
            'hik_port': main_area.hik_port,
            'hik_appKey': main_area.hik_appKey,
            'hik_appSecret': main_area.hik_appSecret,
            'hik_artemis': main_area.hik_artemis,
            'hik_methon': main_area.hik_methon,
            'Mine_id': main_area.Mine_id,
            'created_at': main_area.created_at,
            'updated_at': main_area.updated_at,
            'children_list': area_data
        })

    # 构造响应数据，包括分页信息
    response_data = {
        "data": data_list,
        "pagination": {
            "current_page": page,
            "total_pages": pagination.pages,
            "total_items": pagination.total,
            "per_page": per_page
        }
    }

    # 返回 JSON 响应
    return jsonify({'code':200,'data':response_data})


# 海康安防平台资源信息展示（安防平台）
@hik_security_platform_info_view.route('/hik_security_platform_resource_data', methods=['GET'])
# @jwt_required()
def hik_security_platform_resource_data():
    """
    海康安防平台资源信息展示
    id (str)  二级区域id

    page (str)  第几页
    per_page (str)  每页条数
    """

    # 点击二级区域详情获取下方对应数据，及二级区域主数据

    # 二级区域安防信息id
    id = request.args.get('id',None)

    # 第几页
    page = request.args.get('page', default=1, type=int)
    # 每页条数
    per_page = request.args.get('per_page', default=15, type=int)

    params = [id]

    # 当必传参数没填，返回错误
    if not all(params):
        return jsonify({'code': 400, 'msg': '参数状态未有！'})


    # 二级区域信息
    res = convert_folder_to_dict_list(
        db.session.query(Hik_security_platform_up_area).filter(
            Hik_security_platform_up_area.id == id
        ).first(),
        ['id', 'indexCode', 'name', 'hik_info_id',
         'created_at', 'updated_at']
    )

    if res:

        # 序列化查找子设备信息并进行分页
        res_children_query = db.session.query(Equipment).filter(
            Equipment.Hik_id == id, Equipment.parent_id != None
        )

        # 使用 paginate() 方法进行分页
        res_children = res_children_query.paginate(page=page, per_page=per_page, error_out=False)

        # 将分页结果转换为字典列表
        res_children_list = convert_folder_to_dict_list(res_children.items,
                                                        ['id', 'equipment_type', 'manufacturer_type', 'equipment_name',
                                                         'equipment_ip','Hik_id','Hik_rtsp_url','Hik_indexCode','create_time',])


        res['children'] = res_children_list
        res['total'] = res_children.total  # 总记录数
        res['page'] = res_children.page  # 当前页数
        res['pages'] = res_children.pages  # 总页数

    return jsonify({'code': 200, 'msg': "查询成功", 'data': res})


